package mainClient;

import interaction.BDConnection;
import interaction.BDDisconnect;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import utils.StreamUtils;

public class UdpClient extends DefaultClient
{  
  private static final int BUFFER_SIZE = 10000;
  private static final int TIMEOUT = 5000;
  private String m_ip;
  private int m_port; 
  private int m_selfPort;
  private boolean m_isConnected = false;
  private DatagramSocket m_socket;
  private DatagramPacket m_packet;
  private InetAddress m_address;
  
  public UdpClient(int port, String ip, int selfPort)
  {
    m_port = port;
    m_ip = ip;
    m_selfPort = selfPort;    
  }
  
  @Override
  public boolean connect()
  {
    if(m_isConnected == true)
    {
      System.out.println("Попытка повторного соединения");
      return true;
    }
    
    try
    {
      m_socket = new DatagramSocket(m_selfPort);
    }
    catch (SocketException e)
    {   
      System.out.println("Ошибка создания UDP сокета, порт занят");      
      return false;      
    }
    
    try
    {
      m_socket.setSoTimeout(TIMEOUT);
    }
    catch (SocketException e)
    {            
      System.out.println("Ошибка установки таймаута");
      return false;
    }    
    
    try
    {
      m_address = Inet4Address.getByName(m_ip);
    }
    catch (UnknownHostException e)
    {            
      System.out.println("Ошибка определения адреса сервера");
      return false;
    } 
    
    System.out.println("Создан UDP сокет");
    m_packet = new DatagramPacket(new byte[BUFFER_SIZE], BUFFER_SIZE);
    
    BDConnection queryConn = new BDConnection();    
      
    try
    {          
      if(StreamUtils.fillDatagramPacket(m_packet, m_port, m_address, queryConn) == true)
        m_socket.send(m_packet);
      else
        return false;
      
      m_packet = new DatagramPacket(new byte[BUFFER_SIZE], BUFFER_SIZE);
      m_socket.receive(m_packet);
      System.out.println("Принят пакет от " + m_packet.getAddress().toString());
      
      Object obj = StreamUtils.getDatagramObject(m_packet);
      
      if(obj == null)
      {
        m_socket.close();
        return false;
      }
      
      if(obj instanceof BDConnection)
      {
        m_id = ((BDConnection)obj).m_clientId; 
        System.out.println("Принят идентификатор клиента " + m_id.toString());
        m_isConnected = true;
      }          
      else
        System.out.println("Передана необрабатываемая логика, ожидался идентификатор клиента");
    }
    catch (SocketTimeoutException e)
    {
      m_socket.close();
      System.out.println("Нет ответа от сервера в течение 5 секунд");
    }
    catch (IOException e)
    {      
      System.out.println("Ошибка посылки данных через сокет");
    }       
    
    return m_isConnected;
  }

  @Override
  public boolean disconnect()
  {
    BDDisconnect disconn = new BDDisconnect();
    
    if(m_isConnected == false)
    {
      System.out.println("Попытка повторного отключения");
      return true;
    }

    disconn.m_clientId = m_id;        
    m_packet = new DatagramPacket(new byte[BUFFER_SIZE], BUFFER_SIZE);
    
    try
    {
      if(StreamUtils.fillDatagramPacket(m_packet, m_port, m_address, disconn) == true)
        m_socket.send(m_packet);                 
    }
    catch (IOException e)
    {      
      System.out.println("Ошибка посылки данных через UDP сокет");
    }
    
    m_isConnected = false;
    m_socket.close();
    
    return true;
  }

@Override
public String SendBDR() {
	
	return m_ip;
	// TODO Auto-generated method stub
	
}

}
